/**
 * \file BFSTask.h
 * \author Ameen Jaber
 * \author Mohamad Noureddine
 * \author Mohamed Sabra
 * \brief Define BFS task
 */
#ifndef __BFSTASK_H_
#define __BFSTASK_H_

#include <iostream>
#include <cmath>
#include <Task.h>
#include <TFrame.h>
#include <pppnode.h>
//#include <map>
#include <vector>
#include <queue>
#include <pthread.h>
#include <semaphore.h>
#include <sys/time.h>

// class BFSTask
class BFSTask_t : public Task {
    private:
        double t2; //!< time measurement variable
        double t1; //!< time measurement variable
        timeval tim; //!< time value
        PPPGraph graph; //!< pointer to main graph
        WorkQueue * Q; //!< pointer to the thread queue
        Traverse < PPPGraph> BFS;// 
        std::queue <int>  vqueue; //!< queue of yet to be processed nodes
        sem_t mutex;	
        pthread_mutex_t  qmutex; //!< lock on queue
        pthread_mutex_t  gmutex; //!< lock on graph
        pthread_mutex_t  vmutex; //!< lock on edge vector
        std::vector<pthread_mutex_t*> visited_mutex; //!< vector of mutex variables to lock on the bit vector 
        pthread_mutex_t  cmutex; //!< lock on count
        bool initial; //!< Is this the first time I enter
        int count; //!< count the number of merge tasks
        int position; //!< track position of vertices
        int num_vertices; //!< The number of vertices in the graph
    public:
        /**
         * \brief Default constructor
         */
        BFSTask_t();

        /**
         * \brief Constructor
         */
        BFSTask_t(PPPGraph  ,   //!< pointer to input graph
                WorkQueue *, //!< pointer to input task queue
                int 
                );

        /**
         * \brief Destructor
         */
        ~BFSTask_t();

        /**
         * \brief Init function
         */
        void init();

        /**
         * \brief Run method
         */
        virtual void run();

};


// class merge task
class MergeTask_t : public Task {
    private:
        PPPGraph * graph; //!< pointer to main graph
        Traverse <PPPGraph> * BFS; //!< BFS traversla structure
        int  vertex_id; //!< vertex to start from 
        std::queue <int> * vqueue; //!< queue of yet to be processed nodes
        sem_t * mutex;	 
        pthread_mutex_t * qmutex; //!< lock on queue
        pthread_mutex_t * gmutex; //!< lock on GRAPH 
        pthread_mutex_t * vmutex; //!< lock on edge vector
        std::vector<pthread_mutex_t*>* visited_mutex;
        pthread_mutex_t * cmutex; //!< lock on count
        int * count; //!< count of tasks
        int * position; //!< integer to track position of output vertices
        WorkQueue * Q; //!< pointer to input work queue
    public:
        /**
         * \brief Default constructor
         */
        MergeTask_t();

        /**
         * \brief Constructor 
         */
        MergeTask_t(PPPGraph *,             //!< pointer to input graph
                int ,                       // vertex  id	      
                sem_t *,
                pthread_mutex_t *,          //!< lock on queue
                pthread_mutex_t *,          //!< lock on edge vector
                //pthread_mutex_t *,          //!< lock on visited map		
                std::vector<pthread_mutex_t*> *, //!< lock 
                Traverse  <PPPGraph>*,   //!< input traverse BFS structure
                int *, //!< pointer to counter
                pthread_mutex_t *,          //!< lock on count
                int * , //!< pointer to position counter 
                std::queue <int> *, //!< queue of yet to be processed vertices
                pthread_mutex_t *, //!< lock on graph
                WorkQueue *                //!< work queue pointer    
                );

        /**
         * \brief Destructor
         */
        ~MergeTask_t();

        /**
         * \brief Run method
         */
        virtual void run();
};
#endif
